<?php
namespace App\WebSocket;

use EasySwoole\EasySwoole\ServerManager;
use EasySwoole\EasySwoole\Swoole\Task\TaskManager;
use EasySwoole\Socket\AbstractInterface\Controller;

/**
 * Class Index
 *
 * 此类是默认的 websocket 消息解析后访问的 控制器
 *
  1. server 响应client的http请求，读取http请求头。获得client传过来的加密后的AES密钥(encryptAesKey)，读取http请求体，获得client传过来的加密后的请求数据(encryptData)。
 2. server使用自己的RSA私钥(rsaPrivateKey)对加密后的AES密钥(encryptAesKey)进行RSA解密，得到AES密钥(aesKey)
 3. 使用解密后的AES密钥(aesKey)对加密后的请求数据(encryptData),进行AES解密操作，得到解密后的请求数据(data)，该数据为json格式
 4. 对解密后的请求数据(data)进行json解析，然后做相关的响应操作。
 * @package App\WebSocket
 */
class RsaEncryp extends Controller
{
   	const KEYSIZE = 2048;
    const PRIVATEKEY = "/www/wwwroot/SuperIM/Temp/rsa_private_key.pem";
    const PUBLICKEY  = "/www/wwwroot/SuperIM/Temp/rsa_public_key.pem";

  
	//进行数据加密AES
    private static function encrypt($msg, $key="", $method="AES-128-ECB", $options=OPENSSL_RAW_DATA){
        if(empty($key)){
          $key = substr(md5(uniqid(rand(),1)),   8,   16);
          $aesEncryptKey = self::publicEncrypt($key);//加密后的AES钥匙
        }
        $ivlen  = openssl_cipher_iv_length($method);
        $iv     = openssl_random_pseudo_bytes($ivlen);
        $cipher = openssl_encrypt($msg, $method, $key, $options, $iv);
        $sign   = hash('sha256', base64_encode($cipher).$key, $as_binary=false);
       // $cipher = base64_encode( $iv.$hmac.$cipher );
      	$cipher = base64_encode($cipher);
        return array('data'=>$cipher,'sign'=>$sign);
    }
	//进行数据解密AES
    private static function decrypt($cipher, $key,$sign, $method="AES-128-ECB", $options=OPENSSL_RAW_DATA){
        $c       = base64_decode($cipher);
      	$str 	 = $cipher;
        $ivlen   = openssl_cipher_iv_length($method);
        $iv      = substr($c, 0, $ivlen);
        $hmac    = substr($c, $ivlen, $sha2len=32);
        //$cipher  = substr($c, $ivlen+$sha2len);
      	$cipher  = substr($c, $ivlen);
        $msg     = openssl_decrypt($cipher, $method, $key, $options, $iv);
        $calcmac = hash('sha256', $str.$key, $as_binary=false);
        //if( hash_equals($hmac, $calcmac) ) return $msg;//PHP 5.6+ timing attack safe comparison
      	if($sign === $calcmac) return $msg;
        return false;
    }
	//获取公钥
    private static function getPublicKey()
    {
        $pem = file_get_contents(self::PUBLICKEY);
        $publicKey = openssl_pkey_get_public($pem);
        return $publicKey;
    }
    //获取私钥
    private static function getPrivateKey()
    {
        $pem = file_get_contents(self::PRIVATEKEY);
        $privateKey = openssl_pkey_get_private($pem);
        return $privateKey;
    }
    //验证sign
    private static function sign($msg, $algorithm=OPENSSL_ALGO_SHA256){
        $sign = "";
        $key = self::getPrivateKey();
        // OPENSSL_ALGO_SHA256 OPENSSL_ALGO_MD5 OPENSSL_ALGO_SHA1
        openssl_sign($msg, $sign, $key, $algorithm);
        $sign = base64_encode($sign);
        openssl_free_key($key);
        return $sign;
    }
    //验证签名
    private static function verify($msg, $sign, $algorithm=OPENSSL_ALGO_SHA256){
        $sign = base64_decode($sign);
        $key = self::getPublicKey();
        $result = openssl_verify($msg, $sign, $key, $algorithm);
        openssl_free_key($key);
        return $result;
    }
	//公钥加密RSA（加密AES的密钥，发送时候第一步）
    private static function publicEncrypt($source_data) {
        $data = "";
        $key = self::getPublicKey();//获取公钥
        $dataArray = str_split($source_data, self::KEYSIZE/8);//截取256位
        foreach ($dataArray as $value) {
            $encryptedTemp = ""; 
            openssl_public_encrypt($value,$encryptedTemp,$key);
            $data .= $encryptedTemp;
        }
        openssl_free_key($key);
        return base64_encode($data);
    }
    //私钥解密RSA（解密获得AES密钥，接收时候第一步）
    private static function privateDecrypt($eccryptData) {
        $decrypted = "";
        $decodeStr = base64_decode($eccryptData);
        $key = self::getPrivateKey();
        $enArray = str_split($decodeStr, self::KEYSIZE/8);

        foreach ($enArray as $va) {
            $decryptedTemp = "";
            openssl_private_decrypt($va,$decryptedTemp,$key);
            $decrypted .= $decryptedTemp;
        }
        openssl_free_key($key);
        return $decrypted;
    }
	//私钥加密
    private static function privateEncrypt($source_data) {
        $data = "";
        $dataArray = str_split($source_data, self::KEYSIZE/8);
        $key = self::getPrivateKey();
        foreach ($dataArray as $value) {
            $encryptedTemp = ""; 
            openssl_private_encrypt($value,$encryptedTemp,$key);
            var_dump( strlen($encryptedTemp));
            $data .= $encryptedTemp;
        }
        openssl_free_key($key);
        return base64_encode($data);
    }

    private static function publicDecrypt($eccryptData) {
        $decrypted = "";
        $decodeStr = base64_decode($eccryptData);
        $key = self::getPublicKey();
        $enArray = str_split($decodeStr, self::KEYSIZE/8);

        foreach ($enArray as $va) {
            $decryptedTemp = "";
            openssl_public_decrypt($va,$decryptedTemp,$key);
            $decrypted .= $decryptedTemp;
        }
        openssl_free_key($key);
        return $decrypted;
    }
  
    /**
     *数据加密处理
     *
     * @return void
     */
    static function dataEncrypt($content)
    {
      	    
      	$key = substr(md5(uniqid(rand(),1)),   8,   16);
       	//RSA获取到加密数据，进行私钥解密得到AES钥匙
        $aesEncryptKey = self::publicEncrypt($key);//加密后的AES钥匙
  		$encryptContent = self::encrypt($content, $key); //AES加密数据
      
      	/*加密结束*/
      	//decryptData：解密数据，aesEncryptKey：加密后的AES钥匙，content：原始加密数据，encryptContent：AES加密数据，aesDecryptkey：解密后的AES钥匙
      	return array('decryptData'=>json_decode($content,true),'aesEncryptKey'=>$aesEncryptKey,'content'=>$content,'encryptContent'=>$encryptContent['data'],'sign'=>$encryptContent['sign']);


    }
  	/*数据加解密处理
  	Param： 1.$content（加密文本）
    		2.$aesKey（RSA加密后的AES钥匙）
  	*/
  	static function dataDecrypt($content,$aesKey,$sign){
      	/*解密开始*/
       	$aesDecryptkey = self::privateDecrypt($aesKey);//解密后的AES钥匙
        $decryptData  = json_decode(self::decrypt($content, $aesDecryptkey,$sign),true);//通过key进行解密
      	//"messageDirection"改成2
      	
      	$decryptData["messageDirection"] = 2;
      
      	$decryptData = json_encode($decryptData);
     
      	/*解密结束*/
      
      	/*加密开始*/
      	//生成一个16位伪随机字符串作为原始钥匙，用于第二步的加密
  		//$key    = openssl_random_pseudo_bytes(16);
    	$key = substr(md5(uniqid(rand(),1)),   8,   16);
       	//RSA获取到加密数据，进行私钥解密得到AES钥匙
      	
        $aesEncryptKey = self::publicEncrypt($key);//加密后的AES钥匙
  		$encryptContent = self::encrypt($decryptData, $key); //AES加密数据
      
      	/*加密结束*/
      	//decryptData：解密数据，aesEncryptKey：加密后的AES钥匙，content：原始加密数据，encryptContent：AES加密数据，aesDecryptkey：解密后的AES钥匙
      	return array('decryptData'=>json_decode($decryptData,true),'aesEncryptKey'=>$aesEncryptKey,'content'=>$content,'encryptContent'=>$encryptContent['data'],'aesDecryptkey'=>$aesDecryptkey,'sign'=>$encryptContent['sign']);

    }
  
  
  
  	//进行数据加密AES
     static function pushDataEncrypt($msg, $key="", $method="AES-128-ECB", $options=OPENSSL_RAW_DATA){
        if(empty($key)){
          $key = substr(md5(uniqid(rand(),1)),   8,   16);
          $aesEncryptKey = self::publicEncrypt($key);//加密后的AES钥匙
        }
        $ivlen  = openssl_cipher_iv_length($method);
        $iv     = openssl_random_pseudo_bytes($ivlen);
        $cipher = openssl_encrypt($msg, $method, $key, $options, $iv);
        $sign   = hash('sha256', base64_encode($cipher).$key, $as_binary=false);
       // $cipher = base64_encode( $iv.$hmac.$cipher );
      	$cipher = base64_encode($cipher);
      //  return array('data'=>$cipher,'sign'=>$sign);
      	return array('aesEncryptKey'=>$aesEncryptKey,'encryptContent'=>$cipher,'sign'=>$sign,'unreadCount'=>1);
    }
  
  
  
  
}